/**
 * Copyright(c) by JNet Smartware Group.
 * All rights reserved. Not distribution or redistribution without
 * any permission of JNet Smartware Group.
 * 
 * @author thuc
 * 2010/03/15
 * Program: SWTLogin.java
 */
package vn.smartware.co.framework.swt.base;

import java.util.Date;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.SWTResourceManager;

import vn.smartware.co.framework.action.Requester;
import vn.smartware.co.framework.bean.LoginDTO;
import vn.smartware.co.framework.common.BaseConstant;
import vn.smartware.co.framework.exception.ClientException;
import vn.smartware.co.framework.exception.FatalException;
import vn.smartware.co.framework.form.LoginForm;
import vn.smartware.co.framework.plugin.LangResources;
import vn.smartware.co.framework.utils.MsgBoxUtils;
import vn.smartware.co.java.net.commons.Utils;

/**
 * SWTLogin Screen
 * @author thuctt
 */
public class SWTLogin {

	private static Log log = LogFactory.getLog(SWTLogin.class);

	private Shell shell;

	private Button btnCancel;

	private Button btnLogin;

	private Button btnClear;

	private Text txtPassword;

	private Text txtUserName;

	private Group grpLoginInfo;

	private static final int SIZE_X = 430;

	private static final int SIZE_Y = 215;

	private boolean continueFlg = false;

	private boolean checkedFlg = false;
	
	private int loginNo = -1;
	
	/**
	 * Open the window
	 */
	public void open() {
		
		final Display display = Display.getDefault();
		
		Rectangle disRect = Display.getCurrent().getBounds();
		int startX = (disRect.width - SIZE_X) / 2;
		int startY = (disRect.height - SIZE_Y) / 2;
		
		createContents(startX, startY);
		
		txtUserName.setFocus();
		
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		
		if (shell.isDisposed()){
			if (continueFlg){
				new SWTBase(display);
			}
		}
		
		log.debug("main SWTResourceManager disposed.");
		SWTResourceManager.dispose();
		log.debug("main display disposed.");
		display.dispose();
	}

	/**
	 * Create contents of the window
	 * @param startY 
	 * @param startX 
	 */
	protected void createContents(int startX, int startY) {
		
		shell = new Shell(SWT.CLOSE | SWT.TITLE | SWT.APPLICATION_MODAL | SWT.BORDER);
		shell.setSize(SIZE_X, 190);
		shell.setText(LangResources.getText("SWTLogin.shell"));
		shell.setBackground(BaseConstant.COLOR_BGR_BASE);
		shell.setLocation(startX, startY);
		shell.setImage(SWTResourceManager.getImage(SWTLogin.class, BaseConstant.IMG_SYSTEM_ICON));
		shell.addListener(SWT.Traverse, new Listener() {
		    public void handleEvent(Event e) {
		        if (e.detail == SWT.TRAVERSE_ESCAPE) {
		            e.doit = false;
		            closeAction();
		        }
		    }
		});
		
		grpLoginInfo = new Group(shell, SWT.NONE);
		grpLoginInfo.setBackground(BaseConstant.COLOR_BGR_BASE);
		grpLoginInfo.setBounds(10, 20, 400, 85);
		
		final CLabel clblUser = new CLabel(grpLoginInfo, SWT.SHADOW_OUT | SWT.CENTER);
		clblUser.setFont(BaseConstant.FONT_BASE_LABEL);
		clblUser.setBounds(14, 20, 120, 22);
		clblUser.setText(LangResources.getText("SWTLogin.clblUser"));

		txtUserName = new Text(grpLoginInfo, SWT.BORDER);
		txtUserName.setTextLimit(30);
		txtUserName.setTabs(1);
		txtUserName.setFont(BaseConstant.FONT_BASE_TEXT);
		txtUserName.setBackground(BaseConstant.COLOR_TEXT_REQUIRED);
		txtUserName.setBounds(140, 19, 246, 22);
		txtUserName.addFocusListener(new FocusAdapter(){
			public void focusGained(FocusEvent arg0) {
				txtUserName.selectAll();
			}
		});
		
		final CLabel clblPassword = new CLabel(grpLoginInfo, SWT.SHADOW_OUT | SWT.CENTER);
		clblPassword.setFont(BaseConstant.FONT_BASE_LABEL);
		clblPassword.setBounds(14, 50, 120, 22);
		clblPassword.setText(LangResources.getText("SWTLogin.clblPassword"));

		txtPassword = new Text(grpLoginInfo, SWT.PASSWORD | SWT.BORDER);
		txtPassword.setTextLimit(30);
		txtPassword.setTabs(2);
		txtPassword.setFont(BaseConstant.FONT_BASE_TEXT);
		txtPassword.setBackground(BaseConstant.COLOR_TEXT_NORMAL);
		txtPassword.setBounds(140, 50, 246, 22);
		txtPassword.addFocusListener(new FocusAdapter(){
			public void focusGained(FocusEvent arg0) {
				txtPassword.selectAll();
			}
		});
		
		btnClear = new Button(shell, SWT.NONE);
		btnClear.setBounds(10, 115, 120, 25);
		btnClear.setFont(BaseConstant.FONT_BASE_BUTTON);
		btnClear.setText(LangResources.getText("SWTLogin.btnClear"));
		btnClear.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		btnClear.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				clearAction();
			}
		});
		
		btnLogin = new Button(shell, SWT.NONE);
		btnLogin.setBounds(150, 115, 120, 25);
		btnLogin.setFont(BaseConstant.FONT_BASE_BUTTON);
		btnLogin.setText(LangResources.getText("SWTLogin.btnLogin"));
		btnLogin.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		btnLogin.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				loginAction();
			}
		});
		shell.setDefaultButton(btnLogin);
		
		btnCancel = new Button(shell, SWT.NONE);
		btnCancel.setBounds(290, 115, 120, 25);
		btnCancel.setFont(BaseConstant.FONT_BASE_BUTTON);
		btnCancel.setText(LangResources.getText("SWTLogin.btnCancel"));
		btnCancel.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		btnCancel.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				closeAction();
			}
		});
		
		shell.open();
		shell.layout();
	}

	/**
	 * login action
	 */
	private void loginAction() {

		if (isErrors()){
			return;
		}
		
		try {
			LoginForm form = new LoginForm();
			form.setActionForm("loginForm");
			form.setActionMethod("login");
			
			form.setUsername(Utils.toEmpty(txtUserName.getText()));
			form.setPassword(Utils.toEmpty(txtPassword.getText()));
			form.setLoginDate(new Date());
			form.setLoginIndex(this.loginNo);
			
			form = (LoginForm)Requester.execute(form);
			
			this.loginNo = form.getLoginIndex();
			
			if (form.isLoginSuccess()){
				createUserLoginInfo(form);
				LoginDTO user = LoginDTO.getInstance();
				user.setLoginNo(((LoginDTO)form.getUserDTO()).getLoginNo());
				this.continueFlg = true;
				this.shell.dispose();
				
			}else{
				if (Utils.isNullEmpty(form.getLockOutDate())){
					if (form.getLoginTryNumber() < BaseConstant.MAX_LOGIN_NUMBER){
						MsgBoxUtils.errorMsgBox("errors.LOGING_ERROR",
								new Object[] { Integer.toString(BaseConstant.MAX_LOGIN_NUMBER) });
						
						txtUserName.setFocus();
						
					}else{
						MsgBoxUtils.errorMsgBox("errors.LOGING_ERROR_LOCK",
								new Object[] {Integer.toString(BaseConstant.MAX_LOGIN_NUMBER), form.getUsername()});
						
						grpLoginInfo.setEnabled(false);
						btnClear.setEnabled(false);
						btnLogin.setEnabled(false);
					}
				}else{
					MsgBoxUtils.errorMsgBox("errors.LOGING_ERROR_ACC_LOCKED",
									new Object[] {form.getUsername()});
					
					txtUserName.setFocus();
				}
				
			}
			checkedFlg = true;
		
		} catch (FatalException e) {
			MsgBoxUtils.fatalErrorMsgBox();
			e.printStackTrace();
		}
	}

	/**
	 * create all user login info
	 * @param form
	 */
	private void createUserLoginInfo(LoginForm form) {

		LoginDTO clientUser = LoginDTO.getInstance();
		LoginDTO user = (LoginDTO)form.getUserDTO();
		
		try{
			BeanUtils.copyProperty(clientUser, "userId", new Integer(user.getUserId()));
			BeanUtils.copyProperty(clientUser, "loginName", user.getLoginName());
			BeanUtils.copyProperty(clientUser, "loginPass", user.getLoginPass());
			BeanUtils.copyProperty(clientUser, "name", user.getName());
			BeanUtils.copyProperty(clientUser, "initPrgId", user.getInitPrgId());
			
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * check error
	 * @return boolean
	 */
	private boolean isErrors() {

		if (Utils.isNullEmpty(txtUserName.getText())){
			try {
				MsgBoxUtils.errorMsgBox("errors.NOT_NULL", new Object[]{"UserName"});
				txtUserName.setFocus();
				return true;
			} catch (ClientException e) {
				e.printStackTrace();
			}
		}
		
		return false;
	}

	/**
	 * close action
	 */
	private void closeAction() {
		
		log.info("Cancel action");
		
		try {
			if (!Utils.isNullEmpty(txtUserName.getText())){
				if (checkedFlg){
					LoginForm form = new LoginForm();
					form.setActionForm("loginForm");
					form.setActionMethod("closeAction");
					
					form.setUsername(Utils.toEmpty(txtUserName.getText()));
					form.setPassword(Utils.toEmpty(txtPassword.getText()));
					
					form = (LoginForm)Requester.execute(form);
				}
			}
			
		} catch (FatalException e) {
			MsgBoxUtils.fatalErrorMsgBox();
			e.printStackTrace();
		}
		
		shell.dispose();
	}
	
	/**
	 * clear action
	 */
	private void clearAction() {

		log.info("Clear action");
		txtUserName.setText("");
		txtPassword.setText("");
		txtUserName.setFocus();
	}
}
